import { QueryCondition, QueryOperator } from '../types';

/**
 * 查询工具类
 */
export class QueryUtils {
    /**
     * 检查数据是否匹配查询条件
     * @param data 数据对象
     * @param conditions 查询条件数组
     */
    static matchConditions(data: any, conditions?: QueryCondition[]): boolean {
        if (!conditions || conditions.length === 0) {
            return true;
        }

        return conditions.every(condition => {
            const value = QueryUtils.getFieldValue(data, condition.field);
            return QueryUtils.compareValues(value, condition.operator, condition.value);
        });
    }

    /**
     * 根据条件匹配数据
     * @param data 数据对象
     * @param condition 条件
     */
    static matchCondition(data: any, condition: QueryCondition): boolean {
        const value = QueryUtils.getFieldValue(data, condition.field);
        const conditionValue = condition.value;

        switch (condition.operator) {
            case QueryOperator.EQUALS:
                return value === conditionValue;
            case QueryOperator.NOT_EQUALS:
                return value !== conditionValue;
            case QueryOperator.GREATER_THAN:
                return value > conditionValue;
            case QueryOperator.GREATER_THAN_OR_EQUALS:
                return value >= conditionValue;
            case QueryOperator.LESS_THAN:
                return value < conditionValue;
            case QueryOperator.LESS_THAN_OR_EQUALS:
                return value <= conditionValue;
            case QueryOperator.IN:
                return Array.isArray(conditionValue) && conditionValue.includes(value);
            case QueryOperator.NOT_IN:
                return Array.isArray(conditionValue) && !conditionValue.includes(value);
            case QueryOperator.LIKE:
                return typeof value === 'string' && 
                       typeof conditionValue === 'string' && 
                       value.toLowerCase().includes(conditionValue.toLowerCase());
            default:
                return false;
        }
    }

    /**
     * 获取字段值
     * @param data 数据对象
     * @param field 字段路径（支持点号分隔的路径，如 'user.name'）
     */
    static getFieldValue(data: any, field: string): any {
        if (!data || !field) return undefined;

        // 处理数组索引访问，如 items[0].name
        const parts = field.split(/[.\[\]]+/).filter(Boolean);
        let value = data;

        for (const part of parts) {
            if (value === null || value === undefined) {
                return undefined;
            }

            // 如果是数字，当作数组索引处理
            const index = Number(part);
            if (!isNaN(index) && Array.isArray(value)) {
                value = value[index];
            } else {
                value = value[part];
            }
        }

        return value;
    }

    /**
     * 根据路径获取值
     * @param data 数据对象
     * @param path 路径
     */
    static getValueByPath(data: any, path: string): any {
        return path.split('.').reduce((current, key) => {
            return current ? current[key] : undefined;
        }, data);
    }

    /**
     * 根据路径设置值
     * @param data 数据对象
     * @param path 路径
     * @param value 值
     */
    static setValueByPath(data: any, path: string, value: any): void {
        const keys = path.split('.');
        const lastKey = keys.pop()!;
        const target = keys.reduce((current, key) => {
            current[key] = current[key] || {};
            return current[key];
        }, data);
        target[lastKey] = value;
    }

    /**
     * 比较值是否匹配条件
     * @param value 实际值
     * @param operator 操作符
     * @param compareValue 比较值
     */
    private static compareValues(value: any, operator: QueryOperator, compareValue: any): boolean {
        switch (operator) {
            case QueryOperator.EQUALS:
                return value === compareValue;
            case QueryOperator.NOT_EQUALS:
                return value !== compareValue;
            case QueryOperator.GREATER_THAN:
                return value > compareValue;
            case QueryOperator.GREATER_THAN_OR_EQUALS:
                return value >= compareValue;
            case QueryOperator.LESS_THAN:
                return value < compareValue;
            case QueryOperator.LESS_THAN_OR_EQUALS:
                return value <= compareValue;
            case QueryOperator.IN:
                return Array.isArray(compareValue) && compareValue.includes(value);
            case QueryOperator.NOT_IN:
                return Array.isArray(compareValue) && !compareValue.includes(value);
            case QueryOperator.LIKE:
                return typeof value === 'string' && 
                       typeof compareValue === 'string' && 
                       value.toLowerCase().includes(compareValue.toLowerCase());
            default:
                return false;
        }
    }
}
